home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / Online / Qpopper / pop_updt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-01  |  11.8 KB  |  480 lines

  1. /*
  2.  * Copyright (c) 1989 Regents of the University of California.
  3.  * All rights reserved.  The Berkeley software License Agreement
  4.  * specifies the terms and conditions for redistribution.
  5.  */
  6.  
  7. #ifndef lint
  8. static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
  9. static char SccsId[] = "@(#)@(#)pop_updt.c    2.3  2.3 3/20/91";
  10. #endif 
  11.  
  12. #include <errno.h>
  13. #include <stdio.h>
  14. #include <sys/types.h>
  15. #ifdef SYSV
  16. # include <string.h>
  17. # include <unistd.h>
  18. # include "flock.h"
  19. #else
  20. # include <strings.h>
  21. #endif
  22. #include <sys/stat.h>
  23. #include <sys/file.h>
  24. #include "popper.h"
  25.  
  26. #ifdef MAILOCK
  27. # include <maillock.h>
  28. #endif
  29.  
  30. #if defined(SYSV) && !defined(L_XTND)
  31. #define L_XTND SEEK_END
  32. #endif
  33. #if defined(SYSV) && !defined(L_SET)
  34. #define L_SET SEEK_SET
  35. #endif
  36.  
  37. #if defined(HAVE_UNISTD_H) || defined(SUNOS4)
  38. #include <unistd.h>
  39. #endif
  40.  
  41. extern int      errno;
  42.  
  43. #define        BBSIZE        4096
  44.  
  45. static char standard_error[] =
  46.     "Error updating primary drop. Mail left in temporary maildrop (%d)";
  47.  
  48. /* 
  49.  *  updt:   Apply changes to a user's POP maildrop
  50.  */
  51.  
  52. int pop_updt (p)
  53. POP     *   p;
  54. {
  55.     FILE                *   md;                     /*  Stream pointer for 
  56.                                                         the user's maildrop */
  57.     int                     mfd;                    /*  File descriptor for
  58.                                                         above */
  59.     char                    buffer[BBSIZE];         /*  Read buffer */
  60.  
  61.     char            uidl_buf[128];        /*  UIDL header */
  62.     MsgInfoList         *   mp;                     /*  Pointer to message 
  63.                                                         info list */
  64.     register int            msg_num;                /*  Current message 
  65.                                                         counter */
  66.     register int            status_written;         /*  Status header field 
  67.                                                         written */
  68.     int                     nchar;                  /* Bytes read/written */
  69.  
  70.     long                    offset;                 /* New mail offset */
  71.  
  72.     char        *   result;            /* fget and fputs status */
  73.  
  74.     int                save_errno;            /* Save the error value we
  75.                                are trying to print. */
  76.     struct stat             mybuf;                  /*  For fstat() */
  77.  
  78. #ifdef DEBUG
  79.     if (p->debug) {
  80.         pop_log(p,POP_DEBUG,"Performing maildrop update...");
  81.         pop_log(p,POP_DEBUG,"Checking to see if all messages were deleted");
  82.     }
  83. #endif
  84.  
  85.     if (p->stats) {
  86.         pop_log(p,POP_PRIORITY,"Stats: %s %d %d %d %d",
  87.            p->user, p->msgs_deleted, p->bytes_deleted,
  88.            p->msg_count - p->msgs_deleted,
  89.            p->drop_size - p->bytes_deleted);
  90.     }
  91.  
  92.     if (p->server_mode) {
  93.     if (!p->dirty) {
  94. #ifndef KEEP_TEMP_DROP
  95.         /* Added code in pop_dropcopy.c makes unlink ok now. */
  96.         /* s-dorner@uiuc.edu, 12/91 */
  97.         (void)unlink(p->temp_drop);
  98. #endif
  99.         return(POP_SUCCESS);
  100.     }
  101.  
  102. #ifdef MAILOCK
  103.     /* Use SVR4 mail locking */
  104.     if (maillock(p->user, 1) != 0)
  105.         return(pop_msg(p,POP_FAILURE,"maillock: '%s' (%d)",p->temp_drop,errno));
  106. #endif
  107.     }
  108.  
  109.     if (p->server_mode)
  110.     fstat(fileno(p->drop), &mybuf);
  111.  
  112.     if ((p->msgs_deleted == p->msg_count) &&
  113.     (!p->server_mode || (mybuf.st_size == p->spool_end))) {
  114.     /* Truncate before close, to avoid race condition.  */
  115.     (void)ftruncate (fileno(p->drop), (OFF_T)0);
  116. #ifndef KEEP_TEMP_DROP
  117.     /* Added code in pop_dropcopy.c makes unlink ok now. */
  118.     /* s-dorner@uiuc.edu, 12/91 */
  119.     (void)unlink(p->temp_drop);
  120. #endif
  121.     (void)fclose(p->drop);
  122.     if (p->server_mode) {
  123.         (void)fclose(p->hold);
  124. #ifdef MAILOCK
  125.         mailunlock();
  126. #endif
  127.     }
  128.         return (POP_SUCCESS);
  129.     }
  130.  
  131.     if (!p->server_mode) {
  132.  
  133. #ifdef DEBUG
  134.     if (p->debug) 
  135.         pop_log(p,POP_DEBUG,"Opening mail drop \"%s\"", p->drop_name);
  136. #endif
  137.  
  138. #ifdef MAILOCK
  139.     /* Use SVR4 mail locking */
  140.     if (maillock(p->user, 1) != 0)
  141.         return(pop_msg(p,POP_FAILURE,"maillock: '%s' (%d)",
  142.                             p->drop_name, errno));
  143. #endif
  144.  
  145.     /*  Open the user's real maildrop */
  146.     if ((mfd = open(p->drop_name,O_RDWR|O_CREAT,0660)) == -1 ||
  147.         (md = fdopen(mfd,"r+")) == NULL) {
  148. #ifdef MAILOCK
  149.         mailunlock();
  150. #endif
  151.         return pop_msg(p,POP_FAILURE, standard_error, errno);
  152.     }
  153.     } else {
  154. #ifdef MAILOCK
  155.     /* Use SVR4 mail locking */
  156.     if (maillock(p->user, 1) != 0)
  157.         return(pop_msg(p,POP_FAILURE,"maillock: '%s' (%d)",
  158.                             p->drop_name, errno));
  159. #endif
  160.     mfd = fileno(p->drop);
  161.     }
  162.  
  163.     /*  Lock the user's real mail drop */
  164.     if ( flock(mfd,LOCK_EX) == -1 )
  165.     {
  166.         (void)fclose(md) ;
  167. #ifdef MAILOCK
  168.     mailunlock();
  169. #endif
  170.         return pop_msg(p,POP_FAILURE, "flock: '%s': %s (%d)", p->drop_name,
  171.             (errno < sys_nerr) ? sys_errlist[errno] : "", errno);
  172.     }
  173.  
  174.     if (!p->server_mode) {
  175.     /* Go to the right places */
  176.     (void)fseek(p->drop, 0, SEEK_END); 
  177.     offset = ftell(p->drop); 
  178.  
  179.     /*  Append any messages that may have arrived during the session 
  180.         to the temporary maildrop */
  181.     while ((nchar = read(mfd, buffer, BBSIZE)) > 0)
  182.         if ( nchar != write(fileno(p->drop), buffer, nchar) ) {
  183.         nchar = -1;
  184.         break ;
  185.         }
  186.     if ( nchar != 0 ) {
  187.         (void)fclose(md) ;
  188. #ifdef MAILOCK
  189.         mailunlock();
  190. #endif
  191.         (void)ftruncate(fileno(p->drop), (OFF_T)offset);
  192.         (void)fclose(p->drop) ;
  193. #ifdef EDQUOT
  194.         if (errno == EDQUOT) {
  195.         pop_msg(p, POP_FAILURE,
  196.     "Overquota: appending messages from mailspool to temporary drop (%d)",
  197.         errno);
  198.         } else
  199. #endif
  200.         pop_msg(p, POP_FAILURE,
  201.           "Error appending messages from mailspool to temporary drop (%d)",
  202.             errno);
  203.     }
  204.  
  205.     fflush(md);
  206.     rewind(md);
  207.     (void)ftruncate(mfd, (OFF_T)0) ;
  208.     (void)lseek(mfd, (OFF_T)0, L_SET);
  209.  
  210.     /* Synch stdio and the kernel for the POP drop */
  211.     rewind(p->drop);
  212.     (void)lseek(fileno(p->drop), (OFF_T)0, L_SET);
  213.  
  214.     /*  Transfer messages not flagged for deletion from the temporary 
  215.         maildrop to the new maildrop */
  216. #ifdef DEBUG
  217.     if (p->debug) 
  218.         pop_log(p,POP_DEBUG,"Creating new maildrop \"%s\" from \"%s\"",
  219.             p->drop_name,p->temp_drop);
  220. #endif
  221.  
  222.     } else {
  223.     /* Move this stuff later */
  224.     fstat(fileno(p->drop), &mybuf);
  225.  
  226.     md = p->hold;    /* Really the temp drop */
  227.     mfd = fileno(md);
  228.     }
  229.  
  230.     if (!p->server_mode || (p->msgs_deleted != p->msg_count)) {
  231.  
  232.     for (msg_num = 0; msg_num < p->msg_count; ++msg_num) {
  233.  
  234.         int inheader;
  235.         int body_lines;
  236.  
  237.         /*  Get a pointer to the message information list */
  238.         mp = &p->mlp[msg_num];
  239.  
  240.         if (mp->del_flag) {
  241. #ifdef DEBUG
  242.         if(p->debug)
  243.             pop_log(p,POP_DEBUG,
  244.             "Message %d flagged for deletion.",mp->number);
  245. #endif
  246.         continue;
  247.         }
  248.  
  249.         (void)fseek(p->drop, mp->offset, SEEK_SET);
  250.  
  251. #ifdef DEBUG
  252.         if(p->debug)
  253.         pop_log(p,POP_DEBUG,"Copying message %d.",mp->number);
  254. #endif
  255.  
  256.         /* Put the From line separator */
  257.         fgets(buffer, MAXMSGLINELEN, p->drop);
  258.         if (fputs(buffer, md) == EOF)
  259.         break;
  260.  
  261.         sprintf(buffer, "%s %s", "X-UIDL:", mp->uidl_str);
  262.         if (fputs(buffer, md) == EOF)
  263.         break;
  264.  
  265.         for(status_written=0,inheader=1;
  266.                     fgets(buffer,MAXMSGLINELEN,p->drop);) {
  267.  
  268.         if (inheader) { /* Header */
  269.  
  270.             /*  A blank line signals the end of the header. */
  271.             if (*buffer == '\n') {
  272. #ifndef NO_STATUS
  273.             if (status_written == 0) {
  274.                 if (mp->retr_flag) {
  275.                 (void)sprintf(buffer, "Status: RO\n\n");
  276.                 } else {
  277.                 (void)sprintf(buffer, "Status: U\n\n");
  278.                 }
  279.             }
  280. #endif
  281.  
  282.             inheader = 0;
  283.             body_lines = 1;
  284.             status_written = 0;
  285.  
  286.             } else if (!strncasecmp(buffer, "X-UIDL:", 7)) {
  287.             continue;    /* Skip all existing UIDL lines */
  288.  
  289.             } else if (!strncasecmp(buffer,"Status:", 7)) {
  290.  
  291.             /*  Update the message status */
  292.             if (mp->retr_flag)
  293.                 sprintf(buffer, "Status: RO\n");
  294.             status_written++;
  295.             }
  296.             /*  Save another header line */
  297.             if (fputs(buffer, md) == EOF)
  298.             break;
  299.  
  300.             } else { /* Body */ 
  301.             if (++body_lines > mp->body_lines)
  302.                 break;
  303.             if (fputs(buffer, md) == EOF)
  304.                 break;
  305.             }
  306.         }
  307.  
  308.         if (ferror(md)) {
  309.         break;
  310.         }
  311.  
  312.         if (p->mmdf_separator) {
  313.         fputs(p->mmdf_separator, md);
  314.         }
  315.     }
  316.  
  317.     /* flush and check for errors now!  The new mail will writen
  318.        without stdio,  since we need not separate messages */
  319.  
  320.     if (ferror(md)) {
  321.         int save_error = errno;
  322.  
  323.         (void)ftruncate(mfd, (OFF_T)0) ;
  324.         (void)fclose(md) ;
  325. #ifdef MAILOCK
  326.         mailunlock();
  327. #endif
  328.         (void)fclose(p->drop) ;
  329. #ifdef EDQUOT
  330.         if (save_errno == EDQUOT)
  331.         return pop_msg(p, POP_FAILURE,
  332.         "Overquota copying messages to Mailspool. Temp drop unchanged (%d)",
  333.             save_errno);
  334.         else
  335. #endif
  336.         return pop_msg(p,POP_FAILURE, standard_error, errno);
  337.     }
  338.  
  339.     (void)fflush(md) ;
  340.     if (ferror(md)) {
  341.         int save_error = errno;
  342.  
  343.         (void)ftruncate(mfd, (OFF_T)0) ;
  344.         (void)close(mfd) ;
  345. #ifdef MAILOCK
  346.         mailunlock();
  347. #endif
  348.         (void)fclose(p->drop);
  349. #ifdef EDQUOT
  350.         if (save_errno == EDQUOT)
  351.         return pop_msg(p, POP_FAILURE,
  352.         "Overquota copying messages to Mailspool. Temp drop unchanged (%d)",
  353.             save_errno);
  354.         else
  355. #endif
  356.         return pop_msg(p,POP_FAILURE, standard_error, errno);
  357.     }
  358.  
  359.     } /* p->msgs_deleted != p->msg_count */
  360.  
  361.     if (p->server_mode) {
  362.     if (mybuf.st_size > p->spool_end) {
  363.         /* Go to the right places */
  364.         (void)lseek(fileno(p->drop), (OFF_T)p->spool_end, L_SET); 
  365.  
  366.         /*  Append any messages that may have arrived during the session 
  367.         to the temporary maildrop */
  368.         while ((nchar = read(fileno(p->drop), buffer, BBSIZE)) > 0)
  369.         if ( nchar != write(mfd, buffer, nchar) ) {
  370.             nchar = -1;
  371.             break ;
  372.         }
  373.  
  374.         if ( nchar != 0 ) {
  375. #ifdef MAILOCK
  376.         mailunlock();
  377. #endif
  378.         (void)ftruncate(mfd, (OFF_T)0) ;
  379.         (void)close(mfd) ;
  380. #ifdef EDQUOT
  381.         if (errno == EDQUOT) {
  382.             pop_msg(p, POP_FAILURE,
  383.     "Overquota: appending messages from mailspool to temporary drop (%d)",
  384.             errno);
  385.         } else
  386. #endif
  387.             pop_msg(p, POP_FAILURE,
  388.         "Error appending messages from mailspool to temporary drop (%d)",
  389.             errno);
  390.         }
  391.     }
  392.  
  393.     rewind(p->drop);
  394.     (void)ftruncate(fileno(p->drop), (OFF_T)0);
  395.     (void)lseek(fileno(p->drop), (OFF_T)0, L_SET);
  396.  
  397.     (void)lseek(mfd, (OFF_T)0, L_SET);
  398.  
  399.     while ((nchar = read(mfd, buffer, BBSIZE)) > 0)
  400.         if (nchar != write(fileno(p->drop), buffer, nchar)) {
  401.         nchar = -1;
  402.         break ;
  403.         }
  404.  
  405.     if ( nchar != 0 ) {
  406.         (void)ftruncate(fileno(p->drop), (OFF_T)0);
  407.         (void)fclose(p->drop);
  408. #ifdef MAILOCK
  409.         mailunlock();
  410. #endif
  411.         (void)fclose(md);
  412. #ifdef EDQUOT
  413.         if (errno == EDQUOT) {
  414.         pop_msg(p, POP_FAILURE,
  415.         "Overquota: copying messages back to mailspool (%d)", errno);
  416.         } else
  417. #endif
  418.         pop_msg(p, POP_FAILURE,
  419.         "Error appending messages from temporary drop to mailspool (%d)",
  420.         errno);
  421.     }
  422.  
  423.     (void)fclose(md);
  424. #ifdef MAILOCK
  425.     mailunlock();
  426. #endif
  427.     (void)ftruncate(mfd, (OFF_T)0);
  428. #ifndef KEEP_TEMP_DROP
  429.     /* Added code in pop_dropcopy.c makes unlink ok now. */
  430.     /* s-dorner@uiuc.edu, 12/91 */
  431.     (void)fclose(p->drop);
  432. #endif
  433.     (void)unlink(p->temp_drop);
  434.     } else {
  435.     /* Go to start of new mail if any */
  436.     (void)lseek(fileno(p->drop), (OFF_T)offset, L_SET);
  437.  
  438.     /* Copy over any new mail that arrived while processing the pop drop */
  439.     while((nchar = read(fileno(p->drop), buffer, BBSIZE)) > 0)
  440.         if ( nchar != write(mfd, buffer, nchar) ) {
  441.         nchar = -1;
  442.         break ;
  443.         }
  444.     if ( nchar != 0 ) {
  445.         int save_error = errno;
  446.  
  447.         (void)ftruncate(mfd, (OFF_T)0) ;
  448.         (void)fclose(md) ;
  449. #ifdef MAILOCK
  450.         mailunlock();
  451. #endif
  452.         (void)fclose(p->drop) ;
  453. #ifdef EDQUOT
  454.         if (save_errno == EDQUOT)
  455.         return pop_msg(p, POP_FAILURE,
  456.         "Overquota copying messages to Mailspool. Temp drop unchanged (%d)",
  457.         save_errno);
  458.         else
  459. #endif
  460.         return pop_msg(p,POP_FAILURE, standard_error, errno);
  461.     }
  462.  
  463.     /*  Close the maildrop and empty temporary maildrop */
  464.     (void)fclose(md);
  465. #ifdef MAILOCK
  466.     mailunlock();
  467. #endif
  468.     (void)ftruncate(fileno(p->drop), (OFF_T)0);
  469. #ifndef KEEP_TEMP_DROP
  470.     /* Added code in pop_dropcopy.c makes unlink ok now. */
  471.     /* s-dorner@uiuc.edu, 12/91 */
  472.     (void)unlink(p->temp_drop);
  473. #endif
  474.     (void)fclose(p->drop);
  475.     }
  476.  
  477.     return(pop_quit(p));
  478. }
  479.  
  480.